#include "ApplicationH.h"


void Application::init()
{
	generalMenu.Init(9);
	shapeSelection.Init(7);
	shapeAddMenu.Init(3);
	
	generalMenu.set(0, "Add Shape");
	generalMenu.set(1, "Draw with cutovers");
	generalMenu.set(2, "Change default drawing option");
	generalMenu.set(3, "Choose Shape");
	generalMenu.set(4, "Add Animation (Ignore Borders)");
	generalMenu.set(5, "Add Animation (With Borders)");
	generalMenu.set(8, "Exit");

	shapeSelection.set(0, "Cancel Selection");
	shapeSelection.set(1, "Erase");
	shapeSelection.set(2, "Bring To Front Screen");
	shapeSelection.set(3, "Bring To Foreground");
	shapeSelection.set(4, "Move Shape");
	shapeSelection.set(5, "Add Animation");

	shapeAddMenu.set(0, "Add Rectangle");
	shapeAddMenu.set(1, "Add Circle");
	shapeAddMenu.set(2, "Back To Menu");

	choiceG = choiceR = choiceS = 0;
	//Default Display Type for Drawing
	setDisplayType(WITH_OVERLAP);

	sizeOfList = 0;
}

Application::~Application()
{
	freeShapeList(listShape);
}

void Application::applicationRun()
{
	  do
	  {
		choiceG = generalMenu.choose();

		switch(choiceG){

        case 1: 
			AppGeneralFirstChoice(); //Create Shape
        break;

		case 2: 
			AppGeneralSecondChoice(); //Draw with cutovers
        break;

		case 3: 
			AppGeneralThirdChoice(); //Change default drawing option
        break;
		
		case 4: 
			AddGeneralFourthChoice(); //Choose Shape
        break;

		case 5:
			AddGeneralFifthChoice();//Add Animation (Ignore Borders)
			break;

		case 6:
			AddGeneralSixChoice();//Add Animation (With Borders)
			break;

		case 9: 
        cout << endl << endl << "Bye Bye thank you :D" << endl; //Exit
			break;

		default: {
			cout << "Not valid, please choose correct option from menu";  
			_getch();
				 }

		}

	  }while(choiceG!=9); //Exit (VIA MAIN)

}

void Application::AppGeneralFirstChoice()
{

	system("cls");
	
	do
	{
		choiceS = shapeAddMenu.choose();

		switch(choiceS){

			case 1: 
				AppShapeFirstChoice(); //Create Shape
			break;

			case 2: 
				AppShapeSecondChoice(); //Draw with cutovers
			break;

			case 3:
				break;
		}
	    
	}while(choiceS!=3);
	
}

void Application::AppShapeFirstChoice()
{
	int x, y, w, z;
	
	Rectangl * newRectangle = new Rectangl;
	//ListRectangle.AddRecToTail(newRectangle); // old design
	//RectangleL.addNewRectangeToHead(newRectangle); // old STL design
	system("cls");
	cout << "Please enter the X coordination" << endl;
	cin >> x;

	cout << "Please enter the Y coordination" << endl;
	cin >> y;	
 
	newRectangle->setPos(x,y);


	cout << "Please enter the vertical x size" << endl;
	cin >> w;

	if(w <= 0)
	{
			while(w <= 0)
			{
				cout << "Please enter valid whole vertical x size" << endl;
		        cin >> w;
			}
	}

	cout << "Please enter the vertical y size" << endl;
	cin >> z;


	if(z <= 0)
	{

			while(z <= 0)
			{
				cout << "Please enter valid whole vertical y size" << endl;
		        cin >> z;
			}
	}

	newRectangle->setSize(w,z);
	newRectangle->calcRectanglePoint();
	
	listShape.push_front(newRectangle); 
	sizeOfList++;
}

void Application::AppShapeSecondChoice()
{
	int x, y, r;

	Circle * newCircle = new Circle;
	system("cls");
	cout << "Please enter the X coordination" << endl;
	cin >> x;

	cout << "Please enter the Y coordination" << endl;
    cin >> y;	
 
	newCircle->setPos(x,y);

	cout << "Please enter the radius size" << endl;
	cin >> r;

	if(r <= 0)
	{
			while(r <= 0)
			{
				cout << "Please enter valid whole vertical x size" << endl;
		        cin >> r;
			}
	}

	newCircle->setSize(r);

	listShape.push_front(newCircle);
	sizeOfList++;
}


//Draw with cutovers
void  Application::AppGeneralSecondChoice()
{
	list<Shape*>::iterator i;

	system("cls");
	
	if(listShape.empty())
	{
		cerr << "Empty List"; 
		_getch();
		return;
	}

	for(i=listShape.begin(); i != listShape.end(); ++i)
		(*i)->draw(displayType);

	_getch();
}


//Change default drawing option
void Application::AppGeneralThirdChoice()
{
	if (displayType == WITH_OVERLAP){
		setDisplayType(WITHOUT_OVERLAP);
		generalMenu.set(1, "Draw without cutovers");
	}
	else
	{
		setDisplayType(WITH_OVERLAP);
		generalMenu.set(1, "Draw with cutovers");
	}
}



void Application::AddGeneralFourthChoice()
{
	int x, y;
	Shape * temp;

	system("cls");
	
	cout << "Please enter x coordination " << endl;
	cin >> x;

	cout << "Please enter y coordination " << endl;
	cin >> y;
    
	if(isPointExistInList(x,y,&temp))
    {
		goMenuRectangle(temp,x,y);
	}

	else
	{
	   system("cls");
	   cout << "The input point doesn't exist" << endl;
	   cout << "Press any key to go back to the menu" << endl;
	   _getch();
	}
}

//Add Animation (Ignore Borders)
void Application::AddGeneralFifthChoice(){
	
	Animation rectangleAnimation; // creating each time Animation object. will die after the function and so is the temp list that is being created
	//copyShapeList(listShape, listShapeTemp);
	rectangleAnimation.AnimationWithoutClashesPoly(listShape,displayType);
}

//Add Animation (With Borders)
void Application::AddGeneralSixChoice(){
	Animation rectangleAnimation; // creating each time Animation object. will die after the function and so is the temp list that is being created
	copyShapeList(listShape, listShapeTemp);
	setDisplayType(WITHOUT_OVERLAP);
	rectangleAnimation.AnimationWithClashesPoly(listShape, displayType);
	
}


void Application::goMenuRectangle(Shape * r, int x, int y)
{
	system("cls");

	list<Shape *>::iterator i;

		for(i=listShape.begin(); i != listShape.end(); ++i)
			(*i)->draw(displayType);

	r->setSymbol('+');
	r->draw(1);
	
	goAndDrawPointFromUser(x,y,'@');
	
	_getch();

	r->setSymbol('*');

	do
	  {
		choiceR = shapeSelection.choose();

		switch(choiceR){

        case 1: //Cancel Selection
			break;

		case 2: 
			AppRectangleSecondChoice(r); //Erase
			break;

		case 3: 
			AppRectangleThirdChoice(r); //Bring To Front Screen
			break;
		
		case 4: 
			AppRectangleFourthChoice(r); //Bring To Foreground
			break;

		case 5: 
			AppRectangleFifthChoice(r); //Move Rectangle
			break;
		
		case 6:
			AppRectangleSixChoice(r);//Add Animation
			break;
		default: {
			cout << "Not valid, please choose correct option from menu";  
			_getch();
				 }

		}

	  }while(choiceR!=1);


}

void Application::goAndDrawPointFromUser(int x, int y, char c)
{
	if(x < 0 || x >79)
		if(y < 0 || y > 24)
			return;
	
	gotoxy(x,y);
	cout << c;
}

//Erase
void Application::AppRectangleSecondChoice(Shape * r)
{
	if(removeFromList(r)) {
		system("cls");
		cout << "The selected rectangle has been erased" << endl;
		cout << "Press any key to continue ..";
		_getch();
	}
	else cout << "The selected rectangle was not erased"; // not relevant in our application anyway
	
	choiceR = 1;
}

//Bring To Front Screen
void Application::AppRectangleThirdChoice(Shape * r)
{
	listShape.remove(r);
	listShape.push_back(r);
	system("cls");
	cout << "Done !" << endl << endl;
	cout << "Press any key to continue ..";
	_getch();
}

//Bring To Foreground
void Application::AppRectangleFourthChoice(Shape * r)
{
	listShape.remove(r);
	listShape.push_front(r);
	system("cls");
	cout << "Done !" << endl << endl;
	cout << "Press any key to continue ..";
	_getch();
}

//Move Rectangle
void Application::AppRectangleFifthChoice(Shape * r)
{
    int dx,dy,x,y;
	list<Shape *>::iterator i;
    cout << "Move rectangle X by : ";
    cin >> dx;
    cout << "Move rectangle Y by : ";
    cin >> dy;

	r->getPos(x,y);
    r->resetPos(x+dx,y+dy);

    system("cls");
    
	for(i=listShape.begin(); i != listShape.end(); ++i)
		(*i)->draw(displayType);
        
    _getch();
    system("cls");

}

void Application::AppRectangleSixChoice(Shape *r){
	float dx,dy;
	
	cout << endl;
	cout << "Move rectangle X by : ";
	cin >> dx;
	cout << "Move rectangle Y by : ";
	cin >> dy;

	//Now reposition

	r->setMove(dx,dy);
	//Finished reposition 

	system("cls");
	cout << "ok !" << endl << endl;
	cout << "Press any key to continue ..";

	_getch();
	

}

void Application::AppRectangleSevenChoice(Shape *r){
	//TODO Implement

}


bool Application::isPointExistInList(int x, int y, Shape ** shapeOut) // checks - is point from user exists in list of rectangles ?
{
	Point p;
	p.setPos(x,y);
	list<Shape *>::iterator i;

	for(i=listShape.begin(); i != listShape.end(); ++i)
	{
		if((*i)->isPointIn(x,y) || true==true)
		{ 
			cout << " FOUND " << typeid(*(*i)).name();
			_getch();
			*shapeOut = (*i);
			return true;
		}
	}

	return false;
}



bool Application::removeFromList(Shape * r) // remove from list
{
	list<Shape *>::iterator i;
	for(i=listShape.begin(); i != listShape.end(); ++i)
	{
		if((*i) == r)
		{
			listShape.remove(r);
			sizeOfList--;
			return true;
		}
	}
	
	return false;
}

void Application::copyShapeList(list<Shape*> sourcelst, list<Shape*> copylst)
{
	Rectangl* pRec = NULL;
	Circle* pCir = NULL;
	list<Shape*>::iterator i;

	for(i = sourcelst.begin(); i != sourcelst.end(); ++i)
	{	
		if (typeid(*(*i)) == typeid(Rectangl)){
			pRec = new Rectangl; //Allocating
			*pRec = *(dynamic_cast<Rectangl *>(*i)); //Assigning
			if (NULL != pRec)
				copylst.push_back(pRec);
			else
				cerr << "ERROR: Failed to copy list (" << typeid(*(*i)).name() << endl; //Exception
		}
		if (typeid(*(*i)) == typeid(Circle)){
			pCir = new Circle; //Allocating
			*pCir = *(dynamic_cast<Circle *>(*i)); //Assigning
			if (NULL != pCir)
				copylst.push_back(pCir);
			else
				cerr << "ERROR: Failed to copy list (" << typeid(*(*i)).name() << endl; //Exception	
		}

	}

}

void Application::freeShapeList( list<Shape*> &lst )
{
	list<Shape*>::iterator i;
	for (i=lst.begin(); i != lst.end(); ++i)
		delete(*i);
}


